<?php

namespace app\common\service\processes;

use ShidianUtil\Concurrent\Synchronizer;
use ShidianUtil\Utils\StringUtil;
use think\facade\Filesystem;
use think\File;
use think\Image;

/**
 * 图片处理
 * Class ImageProcess
 * @package app\common\service\processes
 */
class ImageProcess implements ProcessInterface
{
    private Synchronizer $synchronizer;

    public function __construct(Synchronizer $synchronizer)
    {

        $this->synchronizer = $synchronizer;
    }

    public function process($path, $savePath, array $style): bool
    {
        $path = $this->getAbsPath($path);

        $success = false;

        $signature = __CLASS__ . $savePath;
        $this->synchronizer->synchronized($signature, function () use (&$success, $path, $savePath, $style) {

            // 原图片不存在
            if (!Filesystem::fileExists($path)) {
                return;
            }

            // 已经存在处理后的图片
            if (Filesystem::fileExists($this->getAbsPath($savePath))) {
                $success = true;
                return;
            }

            // 文件对象
            $file = new File(Filesystem::path($path));

            // 32KB以下的不压缩
            if ($file->getSize() < 32 * 1024) {
                copy($file->getRealPath(), $savePath);
                $success = true;
                return;
            }

            // 图片对象
            $image = Image::open($file);

            if (isset($style['width']) || isset($style['height'])) {
                $style['width'] ??= $image->width();
                $style['height'] ??= $image->height();
                $style['width'] = min($style['width'], $image->width());
                $style['height'] = min($style['height'], $image->height());

                $image->thumb($style['width'], $style['height']);
            }

            $image->save($savePath, null, $style['quality'] ?? 80);

            $success = true;
        });

        return $success;
    }

    private function getAbsPath($path)
    {

        $path = trim($path, '/');
        if (StringUtil::startsWith($path, 'storage')) {
            $path = mb_substr($path, mb_strlen('storage'));
        }
        return $path;
    }
}
